﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Reflection;
using Kristall.Editor;
using Microsoft.Xna.Framework.Audio;
using Kristall.MyGame.Scripts;
using Microsoft.Xna.Framework;
using Kristall.Editor.Commands;
using System.Xml.Serialization;
using Kristall.Engine;
using Kristall.MyGame;
using Kristall.Screens;
using Kristall.MyGame.Animatables;
using Kristall.Engine.Scripts;

namespace Kristall.Editor
{
    public partial class ToolPalette : Form, INotifyPropertyChanged
    {
        #region Fields and Properties
        public LevelEditor LevelEditor;
        private Control xnaWindow;
        public event PropertyChangedEventHandler PropertyChanged;

        ContextMenuStrip xnaWindowContextMenu;
        ToolStripMenuItem rectangleToolToolStripMenuItem;
        ToolStripMenuItem selectToolToolStripMenuItem;
        ToolStripMenuItem copyCoordsMenuItem;
        ToolStripMenuItem setStartPositionMenuItem;
        ToolStripMenuItem setSizeMenuItem;
        ToolStripMenuItem resizeAnimationToolStripMenuItem;
        ToolStripMenuItem horizontallyToolStripMenuItem;
        ToolStripMenuItem verticallyToolStripMenuItem;
        ToolStripMenuItem addWaypointToolStripMenuItem;
        ToolStripMenuItem sendToFrontToolStripMenuItem;
        ToolStripMenuItem sendToBackToolStripMenuItem;

        public Level Level
        {
            get
            {
                return LevelEditor.Level;
            }
        }

        public bool SelectedIsAABB
        {
            get
            {
                return pgProperties.SelectedObject is AABB;
            }
        }

        public static DataFormats.Format AnimatableDataFormat;
        public CommandManager CommandManager = new CommandManager();

        #endregion

        public ToolPalette(LevelEditor levelEditor, Control xnaWindow)
        {
            InitializeComponent();
            this.xnaWindow = xnaWindow;
            LevelEditor = levelEditor;

            this.FormClosing += new FormClosingEventHandler(ToolPalette_FormClosing);
        }

        void ToolPalette_FormClosing(object sender, FormClosingEventArgs e)
        {
            //Cant dispose the xnaWindow Control, have to remove events set to it by hand
            //xnaWindow.Dispose();

            xnaWindow.MouseClick -= xnaWindowMouseClick;
            xnaWindow.MouseMove -= xnaWindowMouseMove;
            xnaWindow.Move -= xnaWindowMove;
        }

        void CommandManager_OnUndo(object sender, EventArgs e)
        {
            //clearSelection();
            pgProperties.Refresh();
        }

        void CommandManager_OnCommandExecute(object sender, EventArgs e)
        {
            pgProperties.Refresh();
        }

        string formatVector(Vector2 v)
        {
            return string.Format("X: {0:0.00}, Y: {1:0.00}", v.X, v.Y);
        }

        void xnaWindow_MouseMove(object sender, MouseEventArgs e)
        {
            tsslMousePosition.Text = "Mouse: " + formatVector(LevelEditor.MouseCoordinates);
            tsslCameraPosition.Text = "Camera: " + formatVector(LevelEditor.Camera.GetPosition());

            if (xnaWindowContextMenu.Visible || crystalContextMenu.Visible)
                return;

            xnaWindow.Focus();
        }

        void commandManager_CurrentCommandChanged(object sender, EventArgs e)
        {
            if (lbHistory.Items.Count > 0)
            { 
                int index = CommandManager.CurrentCommand - 1;
                if (index >= 0 && index < lbHistory.Items.Count)
                    lbHistory.SelectedIndex = index;
            }
        }

        void commandManager_HistoryChanged(object sender, EventArgs e)
        {
            lbHistory.Items.Clear();
            CommandManager.History.ForEach(x => lbHistory.Items.Add(x.Name));
            this.commandManager_CurrentCommandChanged(this, null);
        }

        void xnaWindow_Move(object sender, EventArgs e)
        {
            updateWindowPosition();
        }

        void updateWindowPosition()
        {
            this.SetDesktopLocation(xnaWindow.Left - this.Width - 40, xnaWindow.Top);
        }

        public void TriggerShortcutKey(KeyEventArgs e)
        {
            foreach (var item in menuStrip1.Items)
            {
                ToolStripDropDownItem dropDownItem = (ToolStripDropDownItem)item;

                foreach (var menuItem in dropDownItem.DropDownItems)
                {
                    ToolStripMenuItem mi = menuItem as ToolStripMenuItem;

                    if (mi != null)
                    {
                        if (e.KeyData == mi.ShortcutKeys)
                        {
                            mi.PerformClick();
                            return;
                        }
                    }
                }
            }

            foreach (var menuItem in xnaWindowContextMenu.Items)
            {
                ToolStripMenuItem item = menuItem as ToolStripMenuItem;
                if (item != null)
                {
                    if (e.KeyData == item.ShortcutKeys)
                    {
                        item.PerformClick();
                        return;
                    }
                }
            }

            Animatable animatable = pgProperties.SelectedObject as Animatable;

            if (animatable != null)
            {
                AnimatableSprite animation = animatable.Animations.FirstOrDefault(x => x.FileName == animatable.CurrentAnimationKey);

                if (animation != null)
                {
                    if (e.Shift && e.KeyCode == Keys.Right)
                    {
                        int dx = animation.Texture.Width;
                        if (e.Control)
                        {
                            dx = -dx;
                            CommandManager.ExecuteCommand(new MoveCommand(animatable, new Vector2(animatable.Position.X - dx, animatable.Position.Y)));

                        }

                        CommandManager.ExecuteCommand(new ResizeCommand(animatable, animatable.Width + dx, animatable.Height));
                        CommandManager.ExecuteCommand(new ResizeAnimationCommand(animatable));

                    }
                    else if (e.Shift && e.KeyCode == Keys.Down)
                    {
                        int dy = animation.Texture.Height;
                        if (e.Control)
                        { 
                            dy = -dy;
                            CommandManager.ExecuteCommand(new MoveCommand(animatable, new Vector2(animatable.Position.X, animatable.Position.Y - dy)));
                        }
                        
                        CommandManager.ExecuteCommand(new ResizeCommand(animatable, animatable.Width, animatable.Height + dy));
                        CommandManager.ExecuteCommand(new ResizeAnimationCommand(animatable));

                    }
                    else if (e.Shift && e.KeyCode == Keys.Left)
                    {
                        int dx = animation.Texture.Width;
                        if (e.Control)
                        {
                            dx = -dx;
                        }
                        else
                        { 
                            CommandManager.ExecuteCommand(new MoveCommand(animatable, new Vector2(animatable.Position.X - dx, animatable.Position.Y)));
                        }

                        CommandManager.ExecuteCommand(new ResizeCommand(animatable, animatable.Width + dx, animatable.Height));
                        CommandManager.ExecuteCommand(new ResizeAnimationCommand(animatable));

                    }
                    else if (e.Shift && e.KeyCode == Keys.Up)
                    {
                        int dy = animation.Texture.Height;
                        if (e.Control)
                        {
                            dy = -dy;
                        }
                        else
                        { 
                            CommandManager.ExecuteCommand(new MoveCommand(animatable, new Vector2(animatable.Position.X, animatable.Position.Y - dy)));
                        }
                        CommandManager.ExecuteCommand(new ResizeCommand(animatable, animatable.Width, animatable.Height + dy));
                        CommandManager.ExecuteCommand(new ResizeAnimationCommand(animatable));
                    }

                }
            }
            
            this.OnKeyDown(e);
        }

        void xnaWindow_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Right)
            {
                //Open context menu
                this.Focus(); //Make sure the xna window looses focus

                if (pgProperties.SelectedObject is Crystal)
                {
                    crystalContextMenu.Show(xnaWindow, e.X, e.Y);
                }
                else
                {
                    xnaWindowContextMenu.Show(xnaWindow, e.X, e.Y);
                }
            }
        }

        private void crystalContextMenu_Opening(object sender, CancelEventArgs e)
        {

        }

        private void xnaWindowContextMenu_Opening(object sender, CancelEventArgs e)
        {


            //pasteToolStripMenuItem1.Enabled = false;
            //var clipboardData = Clipboard.GetDataObject().GetData(ToolPalette.AnimatableDataFormat.Name);
            //if (clipboardData != null)
            //    pasteToolStripMenuItem1.Enabled = true;

            //copyToolStripMenuItem1.Enabled = false;
            //if (SelectedIsAABB)
            //    copyToolStripMenuItem1.Enabled = true;

            string coords = LevelEditor.MouseCoordinates.X + ", " + LevelEditor.MouseCoordinates.Y;
            copyCoordsMenuItem.Tag = coords;
            copyCoordsMenuItem.Text = "Copy Coordinates (" + coords + ")";

            if (SelectedIsAABB)
            {
                addWaypointToolStripMenuItem.Enabled = false;
                if (((AABB)pgProperties.SelectedObject).Scripts.Any(x => x is PlatformScript))
                {
                    addWaypointToolStripMenuItem.Enabled = true;
                }

                resizeAnimationToolStripMenuItem.Enabled = false;
                Animatable temp = null;
                if ((temp = pgProperties.SelectedObject as Animatable) != null)
                {
                    if (temp.CurrentAnimation != null)
                        resizeAnimationToolStripMenuItem.Enabled = true;
                }
            }

        }

        public void changeTool(object sender, EventArgs e)
        {
            if (sender == selectTool)
            {
                LevelEditor.CurrentTool = LevelEditor.SelectTool;
            }
            //else if (sender == moveTool)
            //{
            //    LevelEditor.CurrentTool = LevelEditor.MoveTool;
            //}
            else if (sender == rectangleTool)
            {
                LevelEditor.CurrentTool = LevelEditor.RectangleTool;
            }
        }

        void resizeAnimation()
        {
            Animatable animatable = pgProperties.SelectedObject as Animatable;

            if (animatable == null)
                return;

            AnimatableSprite animation = animatable.Animations.FirstOrDefault(x => x.FileName == animatable.CurrentAnimationKey);
            if (animation != null)
            {
                float width = animation.Texture.Width;
                float height = animation.Texture.Height;

                int scaleY = (int)Math.Ceiling(animatable.Bounds.Height / height);
                int scaleX = (int)Math.Ceiling(animatable.Bounds.Width / width);

                animatable.SetSize((int)(scaleX * width), (int)(scaleY * height));
                animation.FrameWidth = (int)(scaleX * width);
                animation.FrameHeight = (int)(scaleY * height);
            }
        }

        void addAnimatable(string fileName)
        {
            Animatable animatable = pgProperties.SelectedObject as Animatable;
            
            if (animatable == null)
                return;

            AnimatableSprite defaultAnimation = AnimatableSprite.LoadForEditor(fileName, LevelEditor.Level.SpriteTextures, LevelEditor.Content);

            animatable.Animations.Add(defaultAnimation);
            animatable.CurrentAnimationKey = defaultAnimation.FileName;

            defaultAnimation.LoadContent(LevelEditor.Level.SpriteTextures, LevelEditor.Level.Content);

            resizeAnimation();
        }

        private void loadSprite_Click(object sender, EventArgs e)
        {
            if (loadSpriteDialog.ShowDialog() == DialogResult.OK)
            {
                for (int i = 0; i < loadSpriteDialog.FileNames.Length; i++)
                {
                    string fileName = loadSpriteDialog.FileNames[i];
                    //Make sure that the selected image is located in a subdir of \Content
                    if (fileName.StartsWith(Kristall.FullContentPath))
                    {
                        addAnimatable(fileName);
                    }
                    else
                    {
                        MessageBox.Show("Please choose a sprite that is located in or a subdir of the Content folder", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                }
            }
        }

        private void newToolStripMenuItem_Click(object sender, EventArgs e)
        {
            LevelEditor.NewLevel();
        }

        private void loadToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (loadLevelDialog.ShowDialog() == DialogResult.OK)
            {
                LevelEditor.LoadLevel(loadLevelDialog.FileName);
                MessageBox.Show("Level \"" + Path.GetFileName(loadLevelDialog.FileName) + "\" Loaded!", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }

        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (saveLevelDialog.ShowDialog() == DialogResult.OK)
            {
                if (LevelEditor.Level.Save(saveLevelDialog.FileName))
                { 
                    MessageBox.Show("Level \"" + Path.GetFileName(saveLevelDialog.FileName) + "\" Saved!", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show("Are you sure you want to exit the level editor?", "Confirm", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.Yes)
            {
                LevelEditor.ExitToMenu();
            }
        }

        private void testEnemy_Click(object sender, EventArgs e)
        {
            Type target = typeof(NPC);
            Type[] ignore = new[] { typeof(NPC), typeof(Enemy) };
            List<Type> npcTypes = Assembly.GetAssembly(typeof(Kristall)).GetTypes().Where(type => target.IsAssignableFrom(type) && !ignore.Contains(type)).ToList();

            PickItem pi = new PickItem(npcTypes.Cast<object>().ToList());

            if (pi.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                Type selectedType = (Type)pi.SelectedItem;
                ConstructorInfo ci = selectedType.GetConstructor(Type.EmptyTypes);

                if (ci != null)
                {
                    NPC instance = (NPC)ci.Invoke(null);
                    instance.LoadContent(LevelEditor.Level);
                    instance.Position = LevelEditor.Camera.ScreenToWorld(Kristall.Viewport * 0.5f);
                    instance.AddToLevel();
                    selectAABB(instance);
                }
            }
        }

        void setupContextMenu()
        {
            xnaWindowContextMenu = new ContextMenuStrip();
            rectangleToolToolStripMenuItem = new ToolStripMenuItem();
            selectToolToolStripMenuItem = new ToolStripMenuItem();
            copyCoordsMenuItem = new ToolStripMenuItem();
            setStartPositionMenuItem = new ToolStripMenuItem();
            setSizeMenuItem = new ToolStripMenuItem();
            resizeAnimationToolStripMenuItem = new ToolStripMenuItem();
            horizontallyToolStripMenuItem = new ToolStripMenuItem();
            verticallyToolStripMenuItem = new ToolStripMenuItem();
            addWaypointToolStripMenuItem = new ToolStripMenuItem();
            sendToFrontToolStripMenuItem = new ToolStripMenuItem();
            sendToBackToolStripMenuItem = new ToolStripMenuItem();

            xnaWindowContextMenu.Opening += new CancelEventHandler(xnaWindowContextMenu_Opening);

            rectangleToolToolStripMenuItem.Click += new EventHandler(rectangleToolToolStripMenuItem_Click);
            rectangleToolToolStripMenuItem.Text = "Rectangle Tool";
            rectangleToolToolStripMenuItem.ShortcutKeys = Keys.Control | Keys.D1;

            selectToolToolStripMenuItem.Click += new EventHandler(selectToolToolStripMenuItem_Click);
            selectToolToolStripMenuItem.Text = "Select Tool";
            selectToolToolStripMenuItem.ShortcutKeys = Keys.Control | Keys.D2;

            copyCoordsMenuItem.Click += new EventHandler(copyCoordsMenuItem_Click);
            copyCoordsMenuItem.Text = "Copy Coordinates";
            //copyCoordsMenuItem.ShortcutKeys;
            
            setStartPositionMenuItem.Click += new EventHandler(setStartPositionMenuItem_Click);
            setStartPositionMenuItem.Text = "Set Start Position Here";
            setStartPositionMenuItem.ShortcutKeys = Keys.Control | Keys.Space;

            setSizeMenuItem.Click += new EventHandler(setSizeMenuItem_Click);
            setSizeMenuItem.Text = "Set Size";
            setSizeMenuItem.ShortcutKeys = Keys.Control | Keys.T;

            resizeAnimationToolStripMenuItem.Click += new EventHandler(resizeAnimationToolStripMenuItem_Click);
            resizeAnimationToolStripMenuItem.Text = "Resize Animation";
            resizeAnimationToolStripMenuItem.ShortcutKeys = Keys.Control | Keys.F;

            horizontallyToolStripMenuItem.Click += new EventHandler(horizontallyToolStripMenuItem_Click);
            horizontallyToolStripMenuItem.Text = "Split Horizontally";

            verticallyToolStripMenuItem.Click += new EventHandler(verticallyToolStripMenuItem_Click);
            verticallyToolStripMenuItem.Text = "Split Vertically";

            addWaypointToolStripMenuItem.Click += new EventHandler(addWaypointToolStripMenuItem_Click);
            addWaypointToolStripMenuItem.Text = "Add Waypoint";
            addWaypointToolStripMenuItem.ShortcutKeys = Keys.Control | Keys.W;

            sendToFrontToolStripMenuItem.Click += new EventHandler(sendToFrontToolStripMenuItem_Click);
            sendToFrontToolStripMenuItem.Text = "Send To Front";
            sendToFrontToolStripMenuItem.ShortcutKeys = Keys.Control | Keys.OemMinus;

            sendToBackToolStripMenuItem.Click += new EventHandler(sendToBackToolStripMenuItem_Click);
            sendToBackToolStripMenuItem.Text = "Send To Back";
            sendToBackToolStripMenuItem.ShortcutKeys = Keys.Control | Keys.Oemplus;


            xnaWindowContextMenu.Items.AddRange(
            new[]{
                rectangleToolToolStripMenuItem,
                selectToolToolStripMenuItem,
                copyCoordsMenuItem,
                setStartPositionMenuItem,
                setSizeMenuItem,
                resizeAnimationToolStripMenuItem,
                horizontallyToolStripMenuItem,
                verticallyToolStripMenuItem,
                addWaypointToolStripMenuItem,
                sendToFrontToolStripMenuItem,
                sendToBackToolStripMenuItem
            });
        }


        MouseEventHandler xnaWindowMouseClick;
        MouseEventHandler xnaWindowMouseMove;
        EventHandler xnaWindowMove;


        private void ToolPalette_Load(object sender, EventArgs e)
        {
            setupContextMenu();

            for (int i = 0; i < selectionGroup.Items.Count; i++)
            {
                selectionGroup.SetSelected(i, true);
            }

            pgProperties.DataBindings.Add("SelectedObject", LevelEditor.SelectTool.SelectionManager, "SelectedObject");

            Directory.CreateDirectory(Level.FullLevelsPath);
            Directory.CreateDirectory(AnimatableSprite.FullSpritesPath);

            saveLevelDialog.InitialDirectory = loadLevelDialog.InitialDirectory = Level.FullLevelsPath;
            loadSpriteDialog.InitialDirectory = AnimatableSprite.FullSpritesPath;

            AnimatableDataFormat = DataFormats.GetFormat("Animatable");

            CommandManager.HistoryChanged += new EventHandler(commandManager_HistoryChanged);
            CommandManager.CurrentCommandChanged += new EventHandler(commandManager_CurrentCommandChanged);
            CommandManager.OnExecute += new EventHandler(CommandManager_OnCommandExecute);
            CommandManager.OnUndo += new EventHandler(CommandManager_OnUndo);

            this.KeyPreview = true;

            btnAddScript.DataBindings.Add("Enabled", this, "SelectedIsAABB");
            loadSprite.DataBindings.Add("Enabled", this, "SelectedIsAABB");

            xnaWindowMouseClick = new MouseEventHandler(xnaWindow_MouseClick);
            xnaWindow.MouseClick += xnaWindowMouseClick;

            xnaWindowMouseMove = new MouseEventHandler(xnaWindow_MouseMove);
            xnaWindow.MouseMove += xnaWindowMouseMove;

            xnaWindowMove = new EventHandler(xnaWindow_Move);
            xnaWindow.Move += xnaWindowMove;

            updateWindowPosition();
        }

        private void btnAddScript_Click(object sender, EventArgs e)
        {
            Type target = typeof(Script);
            List<Type> scriptTypes = Assembly.GetAssembly(typeof(Kristall)).GetTypes().Where(type => target.IsAssignableFrom(type) && type != target).ToList();
            
            PickItem pi = new PickItem(scriptTypes.Cast<object>().ToList());

            if (pi.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                if (pgProperties.SelectedObject is AABB)
                {
                    AABB aabb = (AABB)pgProperties.SelectedObject;

                    Type scriptType = (Type)pi.SelectedItem;

                    ConstructorInfo ci = scriptType.GetConstructor(Type.EmptyTypes);

                    if (ci != null)
                    {
                        Script script = (Script)ci.Invoke(null);
                        script.Load(LevelEditor.Level, aabb);

                        if (script is TriggerScript)
                        {
                            PickItem pickAABB = new PickItem(LevelEditor.Level.AllEntities.Cast<object>().ToList(), "Id");
                            if (pickAABB.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                            {
                                (script as TriggerScript).TargetId = (pickAABB.SelectedItem as AABB).Id;
                                CommandManager.ExecuteCommand(new AddScriptCommand(aabb, script));
                            }
                        }
                        else
                        {
                            CommandManager.ExecuteCommand(new AddScriptCommand(aabb, script));
                        }
                    }
                }
            }
        }

        private void copyCoordsMenuItem_Click(object sender, EventArgs e)
        {
            Clipboard.SetText((string)copyCoordsMenuItem.Tag, TextDataFormat.Text);
            xnaWindow.Focus();
        }

        void selectAABB(AABB aabb)
        {
            LevelEditor.SelectTool.SelectionManager.ClearSelection();
            LevelEditor.SelectTool.SelectionManager.AddSelection(aabb);
        }

        private void insertLight_Click(object sender, EventArgs e)
        {
            Light light = new Light();
            light.Color = new Microsoft.Xna.Framework.Color(1f, 1f, 1f, 0.5f);
            light.Position = LevelEditor.Camera.GetPosition() - light.HalfSize;
            light.LoadContent(Level);
            CommandManager.ExecuteCommand(new AddToLevelCommand(light));
            selectAABB(light);
        }

        private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            string[] s = selectionGroup.SelectedItems.Cast<string>().ToArray();
            LevelEditor.SelectTool.SelectionGroup = s;
            LevelEditor.SelectTool.SelectionManager.ClearSelection();
        }

        private void addCrystal_Click(object sender, EventArgs e)
        {
            Crystal crystal = new Crystal();
            crystal.LoadContent(LevelEditor.Level);
            crystal.Position = LevelEditor.Camera.GetPosition();
            CommandManager.ExecuteCommand(new AddToLevelCommand(crystal));
            selectAABB(crystal);
        }

        private void setStartPositionMenuItem_Click(object sender, EventArgs e)
        {
            //LevelEditor.Level.StartLocation.Position = LevelEditor.MouseCoordinates;
            LevelEditor.Level.StartPosition = LevelEditor.MouseCoordinates;
            LevelEditor.Level.Player.CheckPoint = LevelEditor.Level.StartPosition;
            LevelEditor.Level.Player.Respawn();
        }

        private void btnResizeAnimation_Click(object sender, EventArgs e)
        {
            resizeAnimation();
        }

        private void setSizeMenuItem_Click(object sender, EventArgs e)
        {
            AABB aabb;
            if ((aabb = pgProperties.SelectedObject as AABB) != null)
            {
                SetSize setSizeDialog = new SetSize();
                setSizeDialog.tbX.Text = aabb.Bounds.Width.ToString();
                setSizeDialog.tbY.Text = aabb.Bounds.Height.ToString();

                if (setSizeDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {
                    int x,y;

                    int.TryParse(setSizeDialog.tbX.Text, out x);
                    int.TryParse(setSizeDialog.tbY.Text, out y);

                    CommandManager.ExecuteCommand(new ResizeCommand(aabb, x, y));
                }
                xnaWindow.Focus();
            }
        }

        private void copyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (SelectedIsAABB)
            {
                CommandManager.ExecuteCommand(new CopyCommand((AABB)pgProperties.SelectedObject));
            }
        }

        private void pasteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            CommandManager.ExecuteCommand(new PasteCommand(Level, LevelEditor.MouseCoordinates));
        }

        private void resizeAnimationToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.resizeAnimation();
        }

        private void pgProperties_SelectedObjectsChanged(object sender, EventArgs e)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs("SelectedIsAABB"));
            }

            if(Level != null)
                tsslObjects.Text = "Objects: " + LevelEditor.Level.AllEntities.Count;
        }

        void deleteSelected()
        {
            if (SelectedIsAABB)
            {
                CommandManager.ExecuteCommand(new DeleteCommand(Level, (AABB)pgProperties.SelectedObject));
                clearSelection();
            }
        }

        private void ToolPalette_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Delete)
            {
                deleteSelected();
            }
        }

        private void undoToolStripMenuItem_Click(object sender, EventArgs e)
        {
            CommandManager.Undo();
        }

        private void redoToolStripMenuItem_Click(object sender, EventArgs e)
        {
            CommandManager.Redo();
        }

        private void cutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (SelectedIsAABB)
            {
                CommandManager.ExecuteCommand(new CutCommand(this.Level, (AABB)pgProperties.SelectedObject));
                clearSelection();
            }
        }

        void clearSelection()
        {
            LevelEditor.SelectTool.SelectionManager.ClearSelection();
        }

        private void horizontallyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (pgProperties.SelectedObject is Animatable)
            {
                CommandManager.ExecuteCommand(new SplitCommand(Level, (Animatable)pgProperties.SelectedObject, LevelEditor.MouseCoordinates, "Horizontal"));
                clearSelection();
            }
        }

        private void verticallyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (pgProperties.SelectedObject is Animatable)
            {
                CommandManager.ExecuteCommand(new SplitCommand(Level, (Animatable)pgProperties.SelectedObject, LevelEditor.MouseCoordinates, "Vertical"));
                clearSelection();
            }
        }

        private void playToolStripMenuItem_Click(object sender, EventArgs e)
        {
            LevelEditor.RunLevel();
        }

        private void selectOnDrainedToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (pgProperties.SelectedObject is Crystal)
            {
                pgProperties.SelectedObject = ((Crystal)pgProperties.SelectedObject).OnDrained;
            }
        }

        private void selectOnChargedToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (pgProperties.SelectedObject is Crystal)
            {
                pgProperties.SelectedObject = ((Crystal)pgProperties.SelectedObject).OnCharged;
            }
        }

        private void addWaypointToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (SelectedIsAABB)
            {
                AABB aabb = (AABB)pgProperties.SelectedObject;
                PlatformScript s = aabb.Scripts.FirstOrDefault(x => x.GetType().Equals(typeof(PlatformScript))) as PlatformScript;

                if (s != null)
                {
                    s.Waypoints.Add(new PointF(aabb.Position.X, aabb.Position.Y));
                }
            }
        }

        private void deleteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            deleteSelected();
        }

        private void gotoCoordinatesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SetSize setSizeDialog = new SetSize();

            Vector2 cameraPos = LevelEditor.Camera.GetPosition();
            setSizeDialog.tbX.Text = cameraPos.X.ToString();
            setSizeDialog.tbY.Text = cameraPos.Y.ToString();

            if (setSizeDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                int x, y;

                int.TryParse(setSizeDialog.tbX.Text, out x);
                int.TryParse(setSizeDialog.tbY.Text, out y);

                LevelEditor.Camera.SetPosition(new Vector2(x, y));
                xnaWindow.Focus();
            }
        }

        private void rectangleToolToolStripMenuItem_Click(object sender, EventArgs e)
        {
            LevelEditor.CurrentTool = LevelEditor.RectangleTool;
        }

        private void selectToolToolStripMenuItem_Click(object sender, EventArgs e)
        {
            LevelEditor.CurrentTool = LevelEditor.SelectTool;
        }

        private void btnCheckPoint_Click(object sender, EventArgs e)
        {
            CheckPoint cp = new CheckPoint();
            cp.Center = LevelEditor.Camera.GetPosition();
            cp.LoadContent(Level);
            CommandManager.ExecuteCommand(new AddToLevelCommand(cp));
        }

        private void sendToFrontToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Animatable anim;
            if ((anim = pgProperties.SelectedObject as Animatable) != null)
            {
                CommandManager.ExecuteCommand(new SetLayerDepthCommand(anim, 0));
            }
        }

        private void sendToBackToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Animatable anim;
            if ((anim = pgProperties.SelectedObject as Animatable) != null)
            {
                CommandManager.ExecuteCommand(new SetLayerDepthCommand(anim, 1));
            }
        }

        private void AddWeapon_Click(object sender, EventArgs e)
        {
            Type target = typeof(Weapon);
            Type[] ignore = new[] { typeof(Weapon) };
            List<Type> weaponTypes = Assembly.GetAssembly(typeof(Kristall)).GetTypes().Where(type => target.IsAssignableFrom(type) && !ignore.Contains(type)).ToList();

            PickItem pi = new PickItem(weaponTypes.Cast<object>().ToList());

            if (pi.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                Type selectedType = (Type)pi.SelectedItem;
                ConstructorInfo ci = selectedType.GetConstructor(Type.EmptyTypes);

                if (ci != null)
                {
                    Weapon instance = (Weapon)ci.Invoke(null);
                    instance.LoadContent(LevelEditor.Level);
                    instance.Position = LevelEditor.Camera.ScreenToWorld(Kristall.Viewport * 0.5f);
                    CommandManager.ExecuteCommand(new AddToLevelCommand(instance));
                    selectAABB(instance);
                }
            }
        }

        private void selectObjectToolStripMenuItem_Click(object sender, EventArgs e)
        {
            PickItem pi = new PickItem(LevelEditor.Level.AllEntities.Cast<object>().ToList(), "Id");

            if (pi.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                AABB aabb = (AABB)pi.SelectedItem;
                selectAABB(aabb);
                LevelEditor.Camera.SetPosition(aabb.Center);
            }
        }
    }
}
